Azure Front Door と Azure App Serivce のCORS設定方法を確認してみた
いわさです。
昨今はWeb開発の様々なシーンでCORSを意識する必要があると思います。
先日Static Web AppsからバックエンドのFront DoorやApp ServiceのリソースをFetchした際に、CORSエラーが発生しました。
Front DoorでもCORS対応出来ますし、App Serviceで対応することも出来ます。
それぞれの設定方法を整理してみました。
フロントエンド
Staic Web Appsでホスティングする、サンプルのフロントエンドを用意します。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Hoge</title> </head> <body> <input type="button" value="FrontDoor0" onclick="fetch('https://hoge0505fd.azurefd.net/image1.png');" /> <input type="button" value="AppService0" onclick="fetch('https://hoge0505app.azurewebsites.net/image1.png');" /> <input type="button" value="FrontDoor1" onclick="hoge('https://hoge0505fd.azurefd.net/image1.png');" /> <input type="button" value="AppService1" onclick="hoge('https://hoge0505app.azurewebsites.net/image1.png');" /> <script type="text/javascript"> function hoge(url) { const myHeaders = new Headers(); myHeaders.append('Content-Type', 'image/png'); const myInit = { method: 'GET', headers: myHeaders, mode: 'cors', cache: 'default' }; fetch(url, myInit) } </script> </body> </html>
hoge0505fd.azurefd.net
がFront Doorで、hoge0505app.azurewebsites.net
はApp Serviceです。
作りがかなり雑ですが直接fetchさせるパターンと、Preflightを発生させるためにContent-Type
を設定するパターンと用意しました。
なお、プリフライトリクエストの発生方法は以下を参考にさせて頂きました。
CORS の プリフライト・リクエストを発生させて観察する – ラボラジアン
デプロイ時のデフォルトドメインはlively-river-022892310.1.azurestaticapps.net
でした。
Azure App Serviceでの設定
検証内ではApp ServiceはLinux PHP7.4の組み込みイメージを使っています。
App ServiceのCORS設定はとても簡単で、CORSメニューで許可するドメインを設定するだけです。(以下の画像だとAccess-Control-Allow-Credentials
を有効化していますが、この検証内では不要です)
こちらでドメインを許可するだけで、対象リクエストのOriginヘッダーを元にAccess-Control-Allow-Origin
ヘッダーを追加してくれます。
$ curl -I -H "Origin:https://lively-river-022892310.1.azurestaticapps.net" https://hoge0505.azurewebsites.net/image1.png HTTP/1.1 200 OK Content-Length: 109213 Content-Type: image/png Last-Modified: Thu, 05 May 2022 00:06:47 GMT Accept-Ranges: bytes ETag: "1aa9d-5de388491448c" Server: Apache Access-Control-Allow-Origin: https://lively-river-022892310.1.azurestaticapps.net Date: Thu, 05 May 2022 01:34:24 GMT
$ curl -I -H "Origin:https://lively-river-022892310.2.azurestaticapps.net" https://hoge0505.azurewebsites.net/image1.png HTTP/1.1 200 OK Content-Length: 109213 Content-Type: image/png Last-Modified: Thu, 05 May 2022 00:06:47 GMT Accept-Ranges: bytes ETag: "1aa9d-5de388491448c" Server: Apache Date: Thu, 05 May 2022 01:34:19 GMT
さらに、今回のケースだとプリフライトリクエスト時はContent-Type
なども考慮する必要がありますが、こちらも自動で付与してくれます。(Access-Control-Allow-Headers
)
一点注意があって、アプリケーション側で独自にCORSコードを適用している場合、App Service CORSと併用するとApp Service CORSが優先される仕様となっています。
App Service側の設定は許可オリジンを設定する形なので、それ以上の設定(特定パスのみAllowしたい等)が必要であれば、App ServiceのCORSは使わずに独自で制御コードを実装する必要があります。
Azure Front Doorでの設定
Azure Front DoorではApp ServiceのようにCORS自動有効化機能みたいなものはないので、ルールセットを構成し、レスポンスヘッダーを書き換えます。
リクエストヘッダーのOriginを判定条件とし、Access-Control-Allow-Origin
を追加しています。
$ curl -I -H "Origin:https://lively-river-022892310.1.azurestaticapps.net" https://hoge0505fd-e7awfdc3g4bxgffc.z01.azurefd.net/image1.png HTTP/2 200 content-length: 109213 content-type: image/png last-modified: Thu, 05 May 2022 00:06:47 GMT accept-ranges: bytes etag: "1aa9d-5de388491448c" access-control-allow-origin: https://lively-river-022892310.1.azurestaticapps.net x-cache: CONFIG_NOCACHE x-azure-ref: 04SlzYgAAAAD2CUdQIVIgRq477CufnXIlVFlPMDFFREdFMjMwOQA0Mzg3MmFhNy0zMTYxLTQ1NjItOTBlOC1kNzU5NGZiMWZlOTA= date: Thu, 05 May 2022 01:35:30 GMT
ただし、今回のケースだとAccess-Control-Allow-Origin
のみだとプリフライトに失敗します。ルールでヘッダーを設定しているのでAccess-Control-Allow-Headers
が必要であればそちらも追加が必要です。
なお、Front DoorのオリジンがApp Serviceの場合は、Origin
リクエストヘッダーがオリジンまで転送され、App ServiceからAccess-Control-Allow-Origin
を返却出来るので、App Service側で設定も可能でした。ただしキャッシュヒットの注意が必要そうです。
さいごに
本日は、Azure Front Door と Azure App Service のそれぞれでCORS設定を行う方法を確認しました。
CORSがうまく解決出来ない人がいて一緒に調べていたのですが、試してみると App Serviceが手軽に設定出来て感動しました。
Front Doorはより細かい設定が必要にはなりますが、バックエンドヘッダーをオーバーライド出来るので柔軟性は高いですね。App Serviceの紹介の後半で独自CORSについて言及しましたが、APIに手をいれずにFront Doorでカスタマイズする方法もアリかなと思いました。